package ru.spb.osll.myfit.server.services;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import org.apache.log4j.Logger;
import ru.spb.osll.myfit.client.log.LogsService;
import ru.spb.osll.myfit.server.Configurator;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;

public class LogsServiceImpl extends RemoteServiceServlet implements LogsService {
  private static Logger s_logger = Logger.getLogger(LogsServiceImpl.class);
  private static final long serialVersionUID = 2843192047334456174L;

  private int m_logTransferSize;
  private String m_testResultsDirectory;

  public LogsServiceImpl() {
    configure();
  }

  private void configure() {
    Configurator configurator = Configurator.getInstance();
    m_testResultsDirectory = configurator.getTestResultsDirectory();

    m_logTransferSize = configurator.getLogTransferSize();
  }

  public Integer getLogTransferSize() {
    return m_logTransferSize;
  }

  private static int lookUpSymbol(byte[] array, int length, byte symbolToLookFor) {
    for (int i = 0; i < length; ++i)
      if (array[i] == symbolToLookFor) return i;
    return -1;
  }

  private void skipBytes(int from, File file, DataInputStream dataInputStream) throws IOException {
    if (file.length() - m_logTransferSize > from) {
      dataInputStream.skipBytes((int)file.length() - m_logTransferSize);
    } else {
      dataInputStream.skipBytes(from);
    }
  }

  private String formAnswer(int bytesRead, byte[] result) {
    if (bytesRead == m_logTransferSize) {
      return new String(Arrays.copyOfRange(result, lookUpSymbol(result, bytesRead, "\n".getBytes()[0]) + 1, bytesRead - 1));
    } else if (bytesRead > 0) {
      return new String(Arrays.copyOf(result, bytesRead - 1));
    }
    return null;
  }

  public String getLogs(String pagePath, String pageId, int from) {
    if (pagePath == null || pageId == null) {
      return null;
    }

    String filePath = m_testResultsDirectory + File.separator + pageId +
        File.separator + pagePath + ".log";

    FileInputStream stream = null;
    File file = new File(filePath);
    if (!file.exists()) return null; //probably the log hasn't been created yet. will open in next request
    try {
      stream = new FileInputStream(filePath);

      DataInputStream dataInputStream = new DataInputStream(stream);

      skipBytes(from, file, dataInputStream);

      int length = (int)Math.min(m_logTransferSize, Math.max(file.length() - from, 0));

      byte[] result = new byte[length];

      int bytesRead = dataInputStream.read(result);

      return formAnswer(bytesRead, result);
    } catch (IOException e) {
      s_logger.error("IO error during reading logfile" + filePath, e);
    } finally {
      try {
        if (stream != null) {
          stream.close();
        }
      } catch (IOException e) {}
    }
    return null;
  }
}